#pragma once

// 使用 pair 需要包含的头文件
#include <utility>
using std::pair;
using std::make_pair;
#include <assert.h>
#include <vector>
using std::vector;
using std::cout;
using std::endl;

enum Color
{
	RED,
	BLACK
};

template<class K, class V>
class RBTreeNode
{
public:
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;
	Color _color;
	pair<K, V> _kv;

	RBTreeNode(const pair<K, V>& kv)
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _color(RED) // 新插入节点默认染红色
		, _kv(kv)
	{}
};

template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
public:
	// 待优化
	bool insert(const pair<K, V>& kv)
	{
		// 1. 搜索二叉树的 [插入操作]
		if (!_root)
		{
			_root = new Node(kv);
			_root->_color = BLACK; // 根节点 _root 染黑色
			return true;
		}

		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			parent = cur;
			if (kv.first > cur->_kv.first)
				cur = cur->_right;
			else if (kv.first < cur->_kv.first)
				cur = cur->_left;
			else
				return false; // 不允许冗余插入
		}

		cur = new Node(kv);
		if (parent->_kv.first < cur->_kv.first)
			parent->_right = cur;
		else
			parent->_left = cur;
		cur->_parent = parent; // 注意要链接 _parent 指针!!!

		// 2. 调整
		while (parent && parent->_color == RED) // parent 为黑色则不用调整
		{
			Node* grandparent = parent->_parent;
			// 2.1. parent 在左
			if (grandparent->_left == parent)
			{
				Node* uncle = grandparent->_right;

				// 2.1.1 [情况 1] : uncle 存在且为红, 变色, 并往上继续调整
				// 2.1.2 [情况 2 + 3]: uncle 不存在或 uncle 存在且为黑, 单旋/双旋 + 变色, 并结束调整
				if (uncle && uncle->_color == RED)
				{
					// [情况 1]
					// 变色: 把 grandparent 的黑色传染给自己两个儿子
					parent->_color = BLACK;
					uncle->_color = BLACK;
					grandparent->_color = RED;

					// 往上继续调整
					cur = grandparent;
					parent = cur->_parent;
					continue;
				}
				else
				{
					// [情况 2 + 3]
					// 右单旋 + 变色
					if (parent->_left == cur)
					{
						rotateR(grandparent);
						parent->_color = BLACK;
						grandparent->_color = RED;
					}
					// 左单旋 + 右单旋 + 变色
					else
					{
						rotateL(parent);
						rotateR(grandparent);
						cur->_color = BLACK;
						grandparent->_color = RED;
					}
					break;
				}
			}
			// 2.2 parent 在右
			else
			{
				Node* uncle = grandparent->_left;

				// 2.2.1 [情况 1] : uncle 存在且为红, 变色, 并往上继续调整
				// 2.2.2 [情况 2 + 3]: uncle 不存在或 uncle 存在且为黑, 单旋/双旋 + 变色, 并结束调整
				if (uncle && uncle->_color == RED)
				{
					// [情况 1]
					// 变色: 把 grandparent 的黑色传染给自己两个儿子
					parent->_color = BLACK;
					uncle->_color = BLACK;
					grandparent->_color = RED;

					// 往上继续调整
					cur = grandparent;
					parent = cur->_parent;
					continue;
				}
				else
				{
					// [情况 2 + 3]
					// 左单旋 + 变色
					if (parent->_right == cur)
					{
						rotateL(grandparent);
						parent->_color = BLACK;
						grandparent->_color = RED;
					}
					// 右单旋 + 左单旋 + 变色
					else
					{
						rotateR(parent);
						rotateL(grandparent);
						cur->_color = BLACK;
						grandparent->_color = RED;
					}
					break;
				}
			}
		}

		_root->_color = BLACK; // 无论如何, _root 必须染黑色
		return true;
	}

	void inOrder()
	{
		inOrderHelper(_root);
		cout << endl;
	}

	bool isBalance()
	{
		if (_root && _root->_color == RED)
		{
			cout << "根节点颜色是红色" << endl;
			return false;
		}

		int benchmark = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_color == BLACK)
				++benchmark;
			cur = cur->_left;
		}

		// 连续红色节点
		return _Check(_root, 0, benchmark);
	}

	int height()
	{
		return getTreeHeight(_root);
	}


private:
	void inOrderHelper(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}

		inOrderHelper(root->_left);
		cout << root->_kv.first << " ";
		inOrderHelper(root->_right);
	}

	bool _Check(Node* root, int blackNum, int benchmark)
	{
		if (root == nullptr)
		{
			if (benchmark != blackNum)
			{
				cout << "某条路径黑色节点的数量不相等" << endl;
				return false;
			}

			return true;
		}

		if (root->_color == BLACK)
		{
			++blackNum;
		}

		if (root->_color == RED
			&& root->_parent
			&& root->_parent->_color == RED)
		{
			cout << "存在连续的红色节点" << endl;
			return false;
		}

		return _Check(root->_left, blackNum, benchmark)
			&& _Check(root->_right, blackNum, benchmark);
	}

	// 左单旋
	void rotateL(Node* parent)
	{
		Node* grandparent = parent->_parent;
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		// 1. subRL 当 parent 的右孩子
		parent->_right = subRL;
		if (subRL)
			subRL->_parent = parent;

		// 2. parent 当 subR 的左孩子
		subR->_left = parent;
		parent->_parent = subR;

		// 3. 处理 grandparent
		subR->_parent = grandparent;
		if (grandparent == nullptr)
		{
			_root = subR;
			_root->_parent = nullptr;
		}
		else
			if (grandparent->_left == parent)
				grandparent->_left = subR;
			else
				grandparent->_right = subR;
	}

	// 右单旋
	void rotateR(Node* parent)
	{
		Node* grandparent = parent->_parent;
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		// 1. subLR 当 parent 的左孩子
		parent->_left = subLR;
		if (subLR)
			subLR->_parent = parent;

		// 2. parent 当 subL 的右孩子
		subL->_right = parent;
		parent->_parent = subL;

		// 3. 处理 grandparent
		subL->_parent = grandparent;
		if (grandparent == nullptr)
		{
			_root = subL;
			_root->_parent = nullptr;
		}
		else
			if (grandparent->_left == parent)
				grandparent->_left = subL;
			else
				grandparent->_right = subL;
	}

	int getTreeHeight(Node* root)
	{
		if (!root)
			return 0;
		int leftH = getTreeHeight(root->_left);
		int rightH = getTreeHeight(root->_right);
		return leftH > rightH ? leftH + 1 : rightH + 1;
	}

public:
	Node* _root = nullptr;
};

void test_3()
{
	int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14, 16, 3, 7, 11, 9, 26, 18, 14, 15 };
	RBTree<int, int> t1;
	for (auto e : a)
	{
		if (e == 14)
		{
			int a = 0;
		}
		t1.insert(make_pair(e, e));
		cout << "插入 : " << e << endl;
		t1.isBalance();
	}

	cout << "中序遍历 : ";
	t1.inOrder();

	if (t1.isBalance())
	{
		cout << "t1 是红黑树" << endl;
	}

	cout << "t1 的高度为 : " << t1.height() << endl;
}

void test_4()
{
	for (int i = 0; i < 5; ++i)
	{
		srand(time(0));
		const size_t N = 1000000;
		RBTree<int, int> t;
		for (size_t i = 0; i < N; i++)
		{
			size_t x = rand() + i;
			t.insert(make_pair(x, 0));
		}

		if (t.isBalance())
		{
			cout << "t 是红黑树。" << endl;
		}
		cout << "t 的高度为 : " << t.height() << endl;
	}
}
